package com.z2.components.orm.separate.aop;

import com.z2.components.Constants.DataSourceKeyConstants;
import com.z2.components.annotation.DataSource;
import com.z2.components.orm.separate.DataSourceContext;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.Ordered;

/**
 * Created by cdyizuoming on 2017/3/16.
 */
@Aspect
public class DataSourceAspect implements Ordered {

    /**
     * 监听标注DataSource的方法切面环绕通知
     *
     * @param pjp
     * @param dataSource
     * @return
     * @throws Throwable
     */
    @Around("execution(public * *(..)) && @annotation(dataSource)")
    public Object onAround(ProceedingJoinPoint pjp, DataSource dataSource) throws Throwable {
        return this.proceed(pjp, dataSource);
    }

    private Object proceed(ProceedingJoinPoint pjp, DataSource dataSource) throws Throwable {
        Object obj = null;
        try {
            String dsKey = this.dsKeyFormat(dataSource.value());
            DataSourceContext.setDataSource(dsKey);
            obj = pjp.proceed();
        } finally {//这里不能捕获异常，否则事务无法回滚
            DataSourceContext.dataSourceRemove();
        }
        return obj;
    }

    private String dsKeyFormat(String dsKey) {
        String key = "";
        if (StringUtils.isBlank(dsKey)) {
            key = DataSourceKeyConstants.WRITE;
        } else if (dsKey.toLowerCase().contains(DataSourceKeyConstants.READ)) {
            key = DataSourceKeyConstants.READ;
        } else if (dsKey.toLowerCase().contains(DataSourceKeyConstants.WRITE)) {
            key = DataSourceKeyConstants.WRITE;
        } else {
            key = DataSourceKeyConstants.WRITE;
        }
        return key;
    }

    /**
     * 解决注解事务先与自定义aop执行,导致自定义aop失效的问题
     * order 值越小，优先级越高
     *
     * @return
     */
    public int getOrder() {
        return 1;
    }

}
